package org.threebitsoftware.tbb.module.vcard;

import java.io.*;

import javax.swing.JPanel;

import org.threebitsoftware.tbb.dao.Address;
import org.threebitsoftware.tbb.dao.Contact;
import org.threebitsoftware.tbb.dao.EmailAddress;
import org.threebitsoftware.tbb.dao.PhoneNumber;
import org.threebitsoftware.tbb.module.fileio.FileOutputInterface;

public class VCardExporter implements FileOutputInterface {

	@Override
	public boolean canExportMultipleContacts() {
		// Multiple contacts are supported
		return true;
	}

	@Override
	public boolean exportContactToFile(String myStrFilePath, Contact myContact)
			throws Exception {
		Contact [] myContacts = new Contact[1];
		
		myContacts[0] = myContact;
		
		return exportContactToFile(myStrFilePath, myContacts);
	}

	@Override
	public boolean exportContactToFile(String myStrFilePath,
			Contact[] myContacts) throws Exception {
		
		boolean result = false;
		BufferedWriter out = null;
		
		try {

			out = new BufferedWriter(new FileWriter(myStrFilePath));
			
			// Write the contacts out to the file
			for (Contact contact : myContacts) {

				out.write("BEGIN:VCARD\r\n");
				out.write("VERSION:3.0\r\n");
				
				/* Write out the FN and N field
				 * 
				 * FN format: FN:<full name>
				 * 
				 * N format: N:<Family Name>;<Given Name>;<Additional Names>;
				 *             <Honorific Prefixes>;<Honorific Suffixes>
				 */
				String prefixStr = contact.getPrefix();
				String firstNameStr = contact.getFirstName();
				String middleNameStr = contact.getMiddleName();
				String lastNameStr = contact.getLastName();
				String suffixStr = contact.getSuffix();

				if ((!prefixStr.isEmpty()) ||
					(!firstNameStr.isEmpty()) ||
					(!middleNameStr.isEmpty()) ||
					(!lastNameStr.isEmpty()) ||
					(!suffixStr.isEmpty())) {
					
					StringBuffer FNStrBuf = new StringBuffer();
					
					FNStrBuf.append("FN:");
					
					if (!prefixStr.isEmpty()) {
						FNStrBuf.append(prefixStr);
					}
					
					if (!firstNameStr.isEmpty()) {
						FNStrBuf.append(" " + firstNameStr);
					}
					
					if (!middleNameStr.isEmpty()) {
						FNStrBuf.append(" " + middleNameStr);
					}
					
					if (!lastNameStr.isEmpty()) {
						FNStrBuf.append(" " + lastNameStr);
					}
					
					if (!suffixStr.isEmpty()) {
						FNStrBuf.append(", " + suffixStr);
					}
					
					String FNStr = FNStrBuf.toString();
					String NStr = new String("N:" + lastNameStr + ";" + 
							firstNameStr + ";" + middleNameStr + ";" + 
							prefixStr + ";" + suffixStr);
					
					out.write(FNStr + "\r\n");
					out.write(NStr + "\r\n");
				}
				
				/* Write out the TITLE field
				 * 
				 * TITLE format: TITLE:<value>
				 */
				String titleStr = contact.getTitle();
				
				if (!titleStr.isEmpty()) {
					String TITLEStr = new String ("TITLE:" + titleStr);
					
					out.write(TITLEStr + "\r\n");
				}
				
				/* Write out the ORG field
				 * 
				 * ORG format: ORG:<organizational name>;<organizational unit #1 name>;<organizational unit #2 name>
				 */
				String companyStr = contact.getCompany();
				
				if (!companyStr.isEmpty()) {
					String ORGStr = new String ("ORG:" + companyStr);
					
					out.write(ORGStr + "\r\n");
				}

				/* Write out the ADR field
				 * 
				 * ADR format: ADR;TYPE=<value>,...:<post office box>;
				 *     <extended address>;<street address>;
				 *     <locality (city)>;<region (state or province>);
				 *     <postal code>;<country name>
				 */
				for (Address address : contact.getAddresses()) {
					
					String addressDescStr = address.getDescription();
					String street1Str = address.getStreet1();
					String street2Str = address.getStreet2();
					String street3Str = address.getStreet3();
					String cityStr = address.getCity();
					String provinceStr = address.getProvince();
					String countryStr = address.getCountry();
					String zipCodeStr = address.getZipCode();
					
					if ((!addressDescStr.isEmpty()) ||
						(!street1Str.isEmpty()) ||
						(!street2Str.isEmpty()) ||
						(!street3Str.isEmpty()) ||
						(!cityStr.isEmpty()) ||
						(!provinceStr.isEmpty()) ||
						(!countryStr.isEmpty()) ||
						(!zipCodeStr.isEmpty())) {

						StringBuffer ADRStrBuf = new StringBuffer();
						
						ADRStrBuf.append("ADR;");
						
						if (!addressDescStr.isEmpty()) {
							if (addressDescStr.equals("Work")) {
								ADRStrBuf.append("TYPE=WORK:");
							}
							else {
								ADRStrBuf.append("TYPE=HOME:");
							}
						}
						else {
							ADRStrBuf.append("TYPE=HOME:");
						}
						
						// Check for PO Box
						String poBoxRegExpStr = 
							new String("^p(ost)?[ |\\.]*o(ffice)?[ |\\.]*(box)?[ 0-9]*[^[a-z ]]*");
						String streetAddrRegExpStr =
							new String("^[a-zA-Z\\d]+(([\\'\\,\\.\\- #][a-zA-Z\\d ])?[a-zA-Z\\d]*[\\.]*)*$");
						String poBoxStr = "";
						String extAddrStr = "";
						String streetAddrStr = "";
						
						if (street1Str.matches(poBoxRegExpStr)) {
							poBoxStr = street1Str;
							
							if (street3Str.matches(streetAddrRegExpStr)) {
								streetAddrStr = street3Str;
								extAddrStr = street2Str;
							} else {
								streetAddrStr = street2Str;
								extAddrStr = street3Str;
							}
						} else if (street2Str.equals(poBoxRegExpStr)) {
							poBoxStr = street1Str;
							
							if (street3Str.matches(streetAddrRegExpStr)) {
								streetAddrStr = street3Str;
								extAddrStr = street1Str;
							} else {
								streetAddrStr = street1Str;
								extAddrStr = street3Str;
							}
						} else if (street3Str.equals(poBoxRegExpStr)) {
							poBoxStr = street3Str;
							
							if (street2Str.matches(streetAddrRegExpStr)) {
								streetAddrStr = street2Str;
								extAddrStr = street1Str;
							} else {
								streetAddrStr = street1Str;
								extAddrStr = street2Str;
							}
						} else if (street1Str.matches(streetAddrRegExpStr)) {
							streetAddrStr = street1Str;
						} else if (street2Str.matches(streetAddrRegExpStr)) {
							streetAddrStr = street2Str;
						} else if (street3Str.matches(streetAddrRegExpStr)) {
							streetAddrStr = street3Str;
						}

						ADRStrBuf.append(poBoxStr + ";" + extAddrStr + ";" +
								streetAddrStr + ";");
						
						if (!cityStr.isEmpty()) {
							ADRStrBuf.append(cityStr + ";");
						} else {
							ADRStrBuf.append(";");
						}
						
						if (!provinceStr.isEmpty()) {
							ADRStrBuf.append(provinceStr + ";");
						} else {
							ADRStrBuf.append(";");
						}
						
						if (!zipCodeStr.isEmpty()) {
							ADRStrBuf.append(zipCodeStr + ";");
						} else {
							ADRStrBuf.append(";");
						}
						
						if (!countryStr.isEmpty()) {
							ADRStrBuf.append(countryStr + ";");
						} else {
							ADRStrBuf.append(";");
						}
						
						String ADRStr = ADRStrBuf.toString();
						
						out.write(ADRStr + "\r\n");
					}
				}
				
				for (PhoneNumber phoneNumber : contact.getPhoneNumbers()) {
					
					String phoneNumberDescStr = phoneNumber.getDescription();
					String phoneNumberStr = phoneNumber.getPhoneNumber();

					
					if ((!phoneNumberDescStr.isEmpty()) ||
						(!phoneNumberStr.isEmpty())) {
						
						StringBuffer TELStrBuf = new StringBuffer();
						
						TELStrBuf.append("TEL;");
						
						if (!phoneNumberDescStr.isEmpty()) {
							if (phoneNumberDescStr.equals("Cellular")) {
								TELStrBuf.append("TYPE=CELL:");
							} else if (phoneNumberDescStr.equals("Work")) {
								TELStrBuf.append("TYPE=WORK:");
							} else {
								TELStrBuf.append("TYPE=HOME:");
							}
						} else {
							TELStrBuf.append("TYPE=HOME:");
						}
						
						TELStrBuf.append(phoneNumberStr);
						
						String TELStr = TELStrBuf.toString();
						
						out.write(TELStr + "\r\n");
					}
				}
				
				for (EmailAddress email : contact.getEmails()) {
					
					String emailDescStr = email.getDescription();
					String emailStr = email.getEmailAddress();
					
					if ((!emailDescStr.isEmpty()) ||
						(!emailStr.isEmpty())) {
						
						StringBuffer EMAILStrBuf = new StringBuffer();
						
						EMAILStrBuf.append("EMAIL;TYPE=INTERNET;");
						
						if (!emailDescStr.isEmpty()) {
							if (emailDescStr.equals("Work")) {
								EMAILStrBuf.append("TYPE=WORK:");
							} else {
								EMAILStrBuf.append("TYPE=HOME:");
							}
						}
						
						EMAILStrBuf.append(emailStr);
						
						String EMAILStr = EMAILStrBuf.toString();
						
						out.write(EMAILStr + "\r\n");
					}
				}
				
				out.write("END:VCARD\r\n");
				
			} // End of for (Contact contact : myContacts) loop
	        
	        out.close();
	        result = true;
	        
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (out != null) {
				out.close();
			}
		}
		
		return result;
	}

	@Override
	public JPanel getGUI() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getMergeClassName() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean iHaveMyOwnGUI() {
		// TODO Auto-generated method stub
		return false;
	}

}
